#include <QLineEdit>
#include <QDateTime>
#include "tablasortfilterproxymodel.h"
#include "formateadortabla.h"

#define FILTRO_COMPARADOR_CONTIENE     0
#define FILTRO_COMPARADOR_IGUAL        1
#define FILTRO_COMPARADOR_MAYOR_IGUAL  2
#define FILTRO_COMPARADOR_MAYOR        3
#define FILTRO_COMPARADOR_MENOR_IGUAL  4
#define FILTRO_COMPARADOR_MENOR        5

#define COMPARAR(comparador,v1,v2) ( \
    comparador == FILTRO_COMPARADOR_IGUAL ? (v1) == (v2) : \
    comparador == FILTRO_COMPARADOR_MAYOR_IGUAL ? (v1) >= (v2) : \
    comparador == FILTRO_COMPARADOR_MAYOR ? (v1) > (v2) : \
    comparador == FILTRO_COMPARADOR_MENOR_IGUAL ? (v1) <= (v2) : \
    comparador == FILTRO_COMPARADOR_MENOR ? (v1) < (v2) : true )

bool TablaSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    bool cumple = true;

    for (int indiceColumna = 0; indiceColumna < listaCamposEdicionFiltros.size(); indiceColumna++) {

        QWidget* widget = const_cast<QWidget*>(listaCamposEdicionFiltros[indiceColumna]);
        QLineEdit* editor = dynamic_cast<QLineEdit*>(widget);
        if (editor == NULL) {
            continue;
        }
        QString textoFiltro = editor->text();

        QString nombreCampo = editor->objectName();

        QModelIndex index = sourceModel()->index(sourceRow, indiceColumna, sourceParent);
        QVariant valor = sourceModel()->data(index);

        bool errorEnFiltro = false;
        cumple = cumple && cumpleFiltro(valor, textoFiltro, errorEnFiltro);
   
        QPalette palette;
        if (errorEnFiltro) {
            palette.setColor(QPalette::Text, Qt::red);
        }
        editor->setPalette(palette);
    }

    return cumple;
}

bool TablaSortFilterProxyModel::cumpleFiltro(const QVariant& valor, QString textoFiltro, bool& errorEnFiltro) const
{
    static char* comparadores[] = { NULL, "=", ">=", ">", "<=", "<" };
    errorEnFiltro = false;

    textoFiltro = textoFiltro.trimmed();
    if (textoFiltro.isEmpty()) {
        return true;
    }

    int comparador = FILTRO_COMPARADOR_CONTIENE;
    for (int i = 1, n = sizeof comparadores / sizeof (char*); i < n; i++) {
        if (textoFiltro.startsWith(comparadores[i])) {
            comparador = i;
            textoFiltro.remove(0, strlen(comparadores[i]));
            break;
        }
    }

    textoFiltro = textoFiltro.trimmed();
    if (textoFiltro.isEmpty()) {
        errorEnFiltro = true;
        return true;
    }

    if (comparador == FILTRO_COMPARADOR_CONTIENE) {
        return valor.toString().contains(textoFiltro, Qt::CaseInsensitive);           
    }

    switch (valor.type()) {
        case QVariant::Date: {
            QDate fecha = QDate::fromString(textoFiltro, FORMATO_FECHA);
            return COMPARAR(comparador, valor.toDate(), fecha);
        }
        case QVariant::DateTime: {
            
            QDateTime fechaHora = QDateTime::fromString(textoFiltro, FORMATO_FECHA);
            if (!fechaHora.isValid()) {
                fechaHora = QDateTime::fromString(textoFiltro, FORMATO_FECHA_HORA);
            }
            if (!fechaHora.isValid()) {
                errorEnFiltro = true;
                return true;
            }
            QString s1 = fechaHora.toString();            
            return COMPARAR(comparador, valor.toDateTime(), fechaHora);
        }
        case QVariant::String:
            return COMPARAR(comparador, valor.toString(), textoFiltro);
        case QVariant::Int:
            return COMPARAR(comparador, valor.toInt(), textoFiltro.toInt());
        case QVariant::UInt:
            return COMPARAR(comparador, valor.toUInt(), textoFiltro.toUInt());
        case QVariant::LongLong:
            return COMPARAR(comparador, valor.toLongLong(), textoFiltro.toLongLong());
        case QVariant::ULongLong:
            return COMPARAR(comparador, valor.toULongLong(), textoFiltro.toULongLong());
        case QVariant::Double:
            return COMPARAR(comparador, valor.toDouble(), textoFiltro.toDouble());


        default:
            errorEnFiltro = true;
            return true;
    }
    
}